﻿using System;
using System.Collections.Concurrent;
using System.Linq;
using ComponentSystem;
using UnityEngine;
using YooAsset;

namespace YooAssetsSystem
{
    /// <summary>
    /// 资源句柄缓存组件
    /// </summary>
    public partial class AssetsHandleCache_Com : ComponentWithId
    {
        /// <summary>
        /// 句柄缓存 使用三元组键值：包名+资源路径+句柄类型
        /// </summary>
        private readonly ConcurrentDictionary<(Type handleType, string pkg, string path), HandleRecord> _cache =
            new ConcurrentDictionary<(Type, string, string), HandleRecord>();
    }

    public partial class AssetsHandleCache_Com
    {
        /// <summary>
        /// 句柄记录结构体
        /// </summary>
        private struct HandleRecord
        {
            /// <summary>
            /// 句柄
            /// </summary>
            public HandleBase Handle;
            /// <summary>
            /// 引用计数
            /// </summary>
            public int RefCount;
        }

        /// <summary>
        /// 添加句柄到缓存
        /// </summary>
        /// <param name="handle">句柄</param>
        /// <param name="pkgName">包名</param>
        /// <param name="assetPath">资源路径</param>
        public void AddHandle(HandleBase handle, string pkgName, string assetPath)
        {
            var key = (handle.GetType(), pkgName, assetPath);
            //Debug.Log($"资源句柄缓存器 要缓存的内容: {(key)}");
            _cache.AddOrUpdate(key,
                k => new HandleRecord { Handle = handle, RefCount = 1 },
                (k, v) =>
                {
                    v.RefCount++;
                    return v;
                });
        }

        /// <summary>
        /// 获取句柄
        /// </summary>
        /// <param name="handleType">句柄类型</param>
        /// <param name="pkgName">包名</param>
        /// <param name="assetPath">资源路径</param>
        public HandleBase GetHandle(Type handleType, string pkgName, string assetPath)
        {
            var key = (handleType, pkgName, assetPath);
            bool isExist = _cache.TryGetValue(key, out var rec);

            if (!isExist)
            {
                Debug.LogError($"资源句柄缓存器 找不到对应的内容: {(key)}");
                return null;
            }

            return rec.Handle;
        }

        /// <summary>
        /// 释放指定资源句柄
        /// </summary>
        /// <param name="handleType">句柄类型</param>
        /// <param name="pkgName">包名</param>
        /// <param name="assetPath">资源路径</param>
        /// <returns>是否释放成功</returns>
        public bool ReleaseHandle(Type handleType, string pkgName, string assetPath)
        {
            var key = (handleType, pkgName, assetPath);

            if (_cache.TryGetValue(key, out var record))
            {
                record.RefCount--;
                if (record.RefCount <= 0)
                {
                    record.Handle.Dispose();
                    return _cache.TryRemove(key, out _);
                }
                return true;
            }
            return false;
        }

        /// <summary>
        /// 强制释放所有关联句柄
        /// </summary>
        /// <param name="assetPath">资源路径</param>
        /// <param name="pkgName">包名</param>
        public void ReleaseAll(string assetPath, string pkgName)
        {
            var keys = _cache.Where(x => x.Key.pkg == pkgName)
                .Where(x => x.Key.path == assetPath)
                .Select(x => x.Key).ToList();

            foreach (var key in keys)
            {
                if (_cache.TryRemove(key, out var record))
                {
                    record.Handle.Dispose();
                }
            }
        }
    }
}